/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*   Nick Kreeger
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*   Nick Kreeger <nick.kreeger@park.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

#import "MailboxItem.h"
#import "MessageWindowService.h"

#import "MailboxesDataSource.h"
#import "NSString+Utils.h"
#import "nsIMsgFolder.h"
#import "nsIMsgWindow.h"
#import "nsMsgBaseCID.h"
#import "nsIFolderListener.h"
#import "nsIRDFResource.h"
#import "nsMsgFolderFlags.h"

NSString* const kMailboxDidAddSubfolder = @"MailboxDidAddSubfolderNotice";

class CHMailboxFolderListener : public nsIFolderListener
{
public:
  CHMailboxFolderListener(MailboxItem* inMailboxItem);
  virtual ~CHMailboxFolderListener();
  
  NS_DECL_ISUPPORTS
  NS_DECL_NSIFOLDERLISTENER
    
private:
  MailboxItem* mMailboxItem;  // weak ref
};

NS_IMPL_ISUPPORTS1(CHMailboxFolderListener, nsIFolderListener)

CHMailboxFolderListener::CHMailboxFolderListener(MailboxItem* inMailboxItem)
{
  mMailboxItem = inMailboxItem;
}

CHMailboxFolderListener::~CHMailboxFolderListener()
{
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item)
{
  nsCOMPtr<nsIMsgFolder> msgFolder = do_QueryInterface(item);
  if (msgFolder)
  {
    // To keep the UI in sync, broadcast this event and let the datasource
    // rebuild itself when it deems necessary.
    [[NSNotificationCenter defaultCenter] postNotificationName:kMailboxDidAddSubfolder
                                                        object:mMailboxItem];
  }
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemRemoved(nsIRDFResource *parentItem, nsISupports *item)
{
  return NS_OK;
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemPropertyChanged(nsIRDFResource *item, 
                                               nsIAtom *property,
                                               const char *oldValue,
                                               const char *newValue)
{
  return NS_OK;
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemIntPropertyChanged(nsIRDFResource *item, 
                                                  nsIAtom *property, 
                                                  PRInt32 oldValue, 
                                                  PRInt32 newValue)
{
  [mMailboxItem updateFolder];
  return NS_OK;
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemBoolPropertyChanged(nsIRDFResource *item, 
                                                   nsIAtom *property, 
                                                   PRBool oldValue, 
                                                   PRBool newValue)
{
  return NS_OK;
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemUnicharPropertyChanged(nsIRDFResource *item,
                                                      nsIAtom *property,
                                                      const PRUnichar *oldValue,
                                                      const PRUnichar *newValue)
{
  return NS_OK;
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemPropertyFlagChanged(nsIMsgDBHdr* item,
                                                   nsIAtom* property, 
                                                   PRUint32 oldFlag,
                                                   PRUint32 newFlag)
{
}

NS_IMETHODIMP 
CHMailboxFolderListener::OnItemEvent(nsIMsgFolder *item, nsIAtom *event)
{
  return NS_OK;
}

#pragma mark -

@implementation MailboxItem

-(id)init
{
  if ((self = [super init]))
  {
    mParent = nil;
    mChildren = nil;
    mIcon = nil;
    mName = nil;
    mAccountKey = nil;
    mRepMsgFolder = nsnull;
    mIsRootFolder = NO;
    mIsStartingUp = YES;
    mDataSourceOwner = nil;
  }
  
  return self;
}

-(id)initWithMsgFolder:(nsIMsgFolder*)aMsgFolder isRootFolder:(BOOL)inIsRootFolder;
{
  if ((self = [super init]))
  {
    mRepMsgFolder = aMsgFolder;
    mParent = nil;
    mChildren = nil;
    mIcon = nil;
    mName = nil;
    mIsRootFolder = inIsRootFolder;
    mDataSourceOwner = nil;
    mIsStartingUp = YES;
    mMailboxFolderListener = new CHMailboxFolderListener(self);
    
    mRepMsgFolder->AddFolderListener(mMailboxFolderListener);
  }
  
  return self;
}

-(void)dealloc
{
  if (mChildren)
    [mChildren release];
  if (mIcon)
    [mIcon release];
  if (mName)
    [mName release];
  if (mAccountKey)
    [mAccountKey release];
  
  //XXX remove folder listener
  
  [super dealloc];
}

-(int)numberOfChildren
{
  if (mChildren)
    return [mChildren count];
  
  return 0;
}

-(BOOL)isGroup
{
  if (mChildren && [mChildren count] > 0)
    return YES;
  
  return NO;
}

-(BOOL)isRootFolder
{
  return mIsRootFolder;
}

-(BOOL)isIMAPFolder
{
  nsresult rv;
  if (!mRepMsgFolder)
    return NO;
  
  nsCOMPtr<nsIMsgIncomingServer> incomingServer;
  rv = mRepMsgFolder->GetServer(getter_AddRefs(incomingServer));
  NS_ENSURE_SUCCESS(rv, NO);
  
  nsXPIDLCString type;
  rv = incomingServer->GetType(getter_Copies(type));
  NS_ENSURE_SUCCESS(rv, NO);
  
  return (type == NS_LITERAL_CSTRING("imap"));
}

-(void)discoverAllFolders
{
  nsCOMPtr<nsIMsgIncomingServer> incomingServer;
  nsresult rv = mRepMsgFolder->GetServer(getter_AddRefs(incomingServer));
  if (NS_SUCCEEDED(rv) && incomingServer)
  {
    nsCOMPtr<nsIMsgWindow> msgWindow = [[MessageWindowService sharedInstance] getTopmostMsgWindow];
    incomingServer->PerformExpand(msgWindow);
  }
}

-(void)removeAllChildren
{
  if (!mChildren)
    return;
  
  [mChildren removeAllObjects];
}

-(MailboxItem*)childAtIndex:(int)inIndex
{
  return [mChildren objectAtIndex:inIndex];
}

-(void)addChild:(MailboxItem*)inChild
{
  if (!mChildren)
    mChildren = [[NSMutableArray alloc] init];
  
  [inChild setParentMailbox:self];
  [mChildren addObject:inChild];
}

-(NSArray*)children
{
  return mChildren;
}

-(void)setParentMailbox:(MailboxItem*)inParentMailbox
{
  if (mParent)
    [mParent release];
  
  mParent = [inParentMailbox retain];
}

-(void)setAccountKey:(NSString*)inAccountKey
{
  [mAccountKey autorelease];
  mAccountKey = [inAccountKey retain];
}

-(void)setDataSourceOwner:(MailboxesDataSource*)aOwner
{
  mDataSourceOwner = aOwner;
}

-(void)updateFolder
{
  // Probably can't call this since it gets called a whole bunch of times...
  //mRepMsgFolder->UpdateFolder(nsnull);  // TODO: Get the message window here...
  if (mDataSourceOwner)
    [mDataSourceOwner updateMailboxItem:self];
}

-(NSString*)displayName
{
  NSString* mailboxName = [self name];
  nsresult rv;
  PRInt32 numUnread;
  rv = mRepMsgFolder->GetNumUnread(PR_FALSE, &numUnread);
  if (NS_SUCCEEDED(rv) && numUnread > 0)
    mailboxName = [mailboxName stringByAppendingFormat:@" (%i)", numUnread];

  return mailboxName;
}

-(NSString*)name
{
  if (!mName)
  {
    nsresult rv;
    PRUnichar* name;
    rv = mRepMsgFolder->GetPrettiestName(&name);
    if (NS_FAILED(rv))
      mName = nil;
    
    else
    {
      mName = [NSString stringWithPRUnichars:name];
      
      //XXX this sucks, I should come up with something bettter.
      // This might be because I am not copying the localizable chrome file. 
      // If I do go this route, these need to be localized.
      if ([mName isEqualToString:@""])
      {
        PRUint32 folderFlag;
        rv = mRepMsgFolder->GetFlags(&folderFlag);
        if (NS_SUCCEEDED(rv))
        {
          if (folderFlag & MSG_FOLDER_FLAG_DRAFTS)
            mName = NSLocalizedString(@"Drafts", nil);
          if (folderFlag & MSG_FOLDER_FLAG_INBOX)
            mName = NSLocalizedString(@"Inbox", nil);
          if (folderFlag & MSG_FOLDER_FLAG_JUNK)
            mName = NSLocalizedString(@"Junk", nil);
          if (folderFlag & MSG_FOLDER_FLAG_SENTMAIL)
            mName = NSLocalizedString(@"Sent", nil);
          if (folderFlag & MSG_FOLDER_FLAG_TEMPLATES)
            mName = NSLocalizedString(@"Templates", nil);
          if (folderFlag & MSG_FOLDER_FLAG_TRASH)
            mName = NSLocalizedString(@"Trash", nil);
          if (folderFlag & MSG_FOLDER_FLAG_QUEUE)
            mName = NSLocalizedString(@"Unsent", nil);
        }
      }
    }
    [mName retain];
  }
  
  return mName;
}

-(NSString*)accountKey
{
  return mAccountKey;
}

-(NSImage*)icon
{
  if (!mIcon)
  {
    if (mIsRootFolder)
      mIcon = [[NSImage imageNamed:@"small_globe.tif"] retain];
    else
    {
      NSString* imageName = @"folder-closed.png";  // default
      PRUint32 folderFlag;
      if (NS_SUCCEEDED(mRepMsgFolder->GetFlags(&folderFlag)))
      {
        if (folderFlag & MSG_FOLDER_FLAG_DRAFTS)
          imageName = @"folder-draft.png";
        if (folderFlag & MSG_FOLDER_FLAG_INBOX)
          imageName = @"folder-inbox.png";
        if (folderFlag & MSG_FOLDER_FLAG_JUNK)
          imageName = @"folder-junk.png";
        if (folderFlag & MSG_FOLDER_FLAG_SENTMAIL)
          imageName = @"folder-sent.png";
        if (folderFlag & MSG_FOLDER_FLAG_TEMPLATES)
          imageName = @"folder-template.png";
        if (folderFlag & MSG_FOLDER_FLAG_TRASH)
          imageName = @"folder-trash.png";
        //if (folderFlag & MSG_FOLDER_FLAG_QUEUE)
        //  imageName = @"Unsent";
      }
      
      mIcon = [[NSImage imageNamed:imageName] retain];
    }
  }
  
  return mIcon;
}

-(MailboxItem*)parentMailbox
{
  return mParent;
}

-(nsIMsgFolder*)representedMsgFolder
{
  return mRepMsgFolder;
}

@end
